#include "AppTask.h"
#include "esp_log.h"
#include "cJSON.h"
#include <app_uart.h>
#include <sstream>
#include "app_mqtt_util.h"
#include "app_uart_util.h"
#include "app_ota.h"

#include "Button.h"
#include "LEDWidget.h"

#include <system/SystemClock.h>
#include <platform/CHIPDeviceLayer.h>
#include <app/server/Server.h>
#include <app/clusters/door-lock-server/door-lock-server.h>

#include "lockly_c_header.h"
#include "uart_util.h"
#include "driver/gpio.h"

#include <esp_matter.h>
#include <esp_matter_core.h>
#include <esp_matter_bridge.h>

#include <app_bridged_device.h>
#include "rf_sensor.h"
#include "app_ecdh.h"
#include "esp_heap_caps.h"
#include <time.h>
#include "lock_event_def.h"
/* BLE */
#include "esp_central.h"
#include "ble_event.h"
#include "mbedtls/base64.h"

static const char * const TAG = "BLE";
#define MAX_PAYLOAD_PER_PACKET 20  // ATT MTU 23 - 3 bytes ATT header
uint8_t BLE_HEAD[4] = {0xa1,0xb2,0xc3,0xd4};
uint8_t weak_up_instruction_ack[8] = {0xA1, 0xB2, 0xC3, 0xD4, 0x08, 0x00, 0x01, 0xF4};  
// 队列句柄
QueueHandle_t bleEventQueue = NULL;

uint16_t g_cen_conn_handle=0xff;         // 保存连接句柄
static bool connectedFlag = false;  // 连接标志位

UartSendEvent EventCache;
// uint32_t bleSendCnt=0,bleSendSuccessCnt=0,bleSendTimeoutCnt=0,lockStateChangeCnt=0;

static int blecent_gap_event(struct ble_gap_event *event, void *arg);


void BleDataForward(void * pvParameter);

esp_timer_handle_t one_shot_timer;
static void one_shot_timer_callback(void *arg)
{
    ESP_LOGI(TAG, "One-shot timer triggered!");
    int rc = ble_gap_terminate(g_cen_conn_handle, BLE_ERR_REM_USER_CONN_TERM);
    printf("Auto disconnect via FreeRTOS timer; conn_handle=%d, rc=%d\n",
           g_cen_conn_handle, rc);

    if(rc)
    {
        if (pdPASS == xQueueReset(bleEventQueue))
        {
            ESP_LOGW(TAG,"bleEventQueue Reset DONE");
        }
        else
        {
            ESP_LOGE(TAG,"bleEventQueue Reset FALSE");
        }
    }

}

void bleCentralEventInit(void)
{
    bleEventQueue = xQueueCreate(10, sizeof(BleEvent));
    if (bleEventQueue == NULL) {
        printf("Failed to create bleEventQueue\n");
        return ESP_FAIL;
    }

    xTaskCreate(BleDataForward, "BleDataForward", 3*1024, NULL, 4, NULL);

    // 定义定时器配置
    const esp_timer_create_args_t one_shot_timer_args = {
        .callback = &one_shot_timer_callback, // 回调函数
        .arg = NULL,                          // 传递给回调函数的参数
        .dispatch_method = ESP_TIMER_TASK,    // 回调函数的调度方式
        .name = "one_shot_timer"              // 定时器名称
    };

    
    esp_err_t err;

    // 创建定时器
    err = esp_timer_create(&one_shot_timer_args, &one_shot_timer);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to create timer: %s", esp_err_to_name(err));
        return;
    }

    /* Initialize data structures to track connected peers. */
    int rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64);
    assert(rc == 0);
}




/**
 * Initiates the GAP general discovery procedure.
 */
void blecent_scan(void)
{
    uint8_t own_addr_type;
    struct ble_gap_disc_params disc_params;
    int rc;

    /* Figure out address to use while advertising (no privacy for now) */
    rc = ble_hs_id_infer_auto(0, &own_addr_type);
    if (rc != 0) {
        MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
        return;
    }

    /* Tell the controller to filter duplicates; we don't want to process
     * repeated advertisements from the same device.
     */
    disc_params.filter_duplicates = 0;

    /**
     * Perform a passive scan.  I.e., don't send follow-up scan requests to
     * each advertiser.
     */
    disc_params.passive = 1;

    /* Use defaults for the rest of the parameters. */
    disc_params.itvl = 0;
    disc_params.window = 0;
    disc_params.filter_policy = 0;
    disc_params.limited = 0;

    if (!ble_gap_disc_active())
    {
        rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params,
                          blecent_gap_event, NULL);
        if (rc != 0)
        {
            MODLOG_DFLT(ERROR, "Error initiating GAP discovery procedure; rc=%d\n",
                        rc);
        }
    }
    else
    {
        ESP_LOGI(TAG, "It is ble scaning...");
    }
}


void send_ble_data_lock_when_connected(uint8_t *data, uint16_t data_len)
{
    struct peer *peer;
    const struct peer_chr *chr;
    int rc;
    if(g_cen_conn_handle == 0xff)
    {
        MODLOG_DFLT(ERROR, "Error in finding peer,there is no connected ,g_cen_conn_handle = %d,data_len = %d",g_cen_conn_handle,data_len);
        return;
    }
    peer = peer_find(g_cen_conn_handle);
    if (peer == NULL)
    {
        MODLOG_DFLT(ERROR, "Error in finding peer, aborting...,g_cen_conn_handle = %d",g_cen_conn_handle);
        if(connectedFlag)
        {
            ble_gap_terminate(g_cen_conn_handle, BLE_ERR_REM_USER_CONN_TERM);
            return;
        }
         return;
    }

    uint8_t chr_find_cnt = 0;
    do
    {
        chr = peer_chr_find_uuid(peer,
                                 BLE_UUID16_DECLARE(0xFFF0),
                                 BLE_UUID16_DECLARE(0xFFF1));
        chr_find_cnt ++;
        vTaskDelay(100/portTICK_PERIOD_MS);
    } while ((chr == NULL) && (chr_find_cnt < 10));

    if (chr == NULL)
    {
        MODLOG_DFLT(ERROR, "Characteristic not found, aborting...");
        return;
    }

    ESP_LOGI("yuezhen,gao","chr_find_cnt = %d",chr_find_cnt);
    // 分包发送数据
    uint16_t offset = 0;
    while (offset < data_len)
    {
        
        uint16_t chunk_len = data_len - offset;
        if (chunk_len > MAX_PAYLOAD_PER_PACKET)
        {
            chunk_len = MAX_PAYLOAD_PER_PACKET;
        }

        rc = ble_gattc_write_flat(g_cen_conn_handle,
                                  chr->chr.val_handle,
                                  data + offset,
                                  chunk_len,
                                  NULL,
                                  NULL);
        if (rc != 0)
        {
            MODLOG_DFLT(ERROR, "Write failed at offset %d, rc = %d", offset, rc);
            return;
        }
        offset += chunk_len;
        // 添加延时，确保从机处理完当前数据
        vTaskDelay(200 / portTICK_PERIOD_MS); // 200ms 延时
    }

    ESP_LOGI(TAG, "Data sent successfully in %d bytes", data_len);
}

/**
 * Called when service discovery of the specified peer has completed.
 */
static void blecent_on_disc_complete(const struct peer *peer, int status, void *arg)
{

    const struct peer_dsc *dsc;
    uint8_t value[2] = {0x01,0x00};
    const struct peer_chr *chr;
    if (status != 0) {
        /* Service discovery failed.  Terminate the connection. */
        MODLOG_DFLT(ERROR, "Error: Service discovery failed; status=%d "
                    "conn_handle=%d\n", status, peer->conn_handle);

        // 这里 连接失败 断开连接 前 需要 把 消息队列清空，防止 滞留信息 在下次 连接成功后 继续发送
        if (pdPASS == xQueueReset(bleEventQueue))
        {
            ESP_LOGW(TAG,"bleEventQueue Reset DONE");
        }
        else
        {
            ESP_LOGE(TAG,"bleEventQueue Reset FALSE");
        }

        ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
        return;
    }

    MODLOG_DFLT(INFO, "Service discovery complete; status=%d "
                "conn_handle=%d\n", status, peer->conn_handle);

    // 使能 0xFFF4 的 notify
    dsc = peer_dsc_find_uuid(peer,
                             BLE_UUID16_DECLARE(0xFFF0),
                             BLE_UUID16_DECLARE(0xFFF4),
                             BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16));

    int rc = ble_gattc_write_flat(peer->conn_handle, dsc->dsc.handle,
                              value, sizeof value, NULL, arg);
    if(rc != 0)
    {
        ESP_LOGE(TAG,"subscribe error");
        return;
    }
    
    // 连接后延时150ms确保能够正常发送消息
    vTaskDelay(150 / portTICK_PERIOD_MS);
    // 发送唤醒指令
    uint8_t weak_up_inst[9] = {0xA1, 0xB2, 0xC3, 0xD4, 0x09, 0x00, 0x01, 0x0F, 0xF3};
    // ble_gattc_write_flat(peer->conn_handle, dsc->dsc.handle,weak_up_inst, 9,NULL, arg);

    chr = peer_chr_find_uuid(peer,
                             BLE_UUID16_DECLARE(0xFFF0),
                             BLE_UUID16_DECLARE(0xFFF1));

    rc = ble_gattc_write_flat(g_cen_conn_handle,
                              chr->chr.val_handle,
                              weak_up_inst,
                              9,
                              NULL,
                              NULL);
}

// 连接锁端蓝牙模块,并发送消息
void ble_send_data_to_lock(uint8_t *peer_addr, uint8_t *data, uint16_t data_lenght, MqttData_t *src, UartSendParm parm, uint16_t timeout)
{
    int rc;
    ble_addr_t addr;
    static BleEvent ble_msg;
    ble_msg.len = data_lenght;
    memcpy(ble_msg.buf,data,data_lenght);

     // 发送到队列尾部，阻塞最长 100ms
    if (xQueueSend(bleEventQueue, &ble_msg, pdMS_TO_TICKS(100)) != pdPASS)
    {
        // 队列满，发送失败
        printf("ble send data Producer: queue full, drop event\n");
    }
    else
    {
        printf("ble send data  Producer: event sent, len=%ld\n", ble_msg.len);
    }

    EventCache.src = src;
    EventCache.handler = parm.handler;
    EventCache.sub_command_type = parm.command;
    EventCache.buf = data;
    EventCache.len = data_lenght;
    EventCache.dest = app_bridge_get_device_by_espnow_macaddr((uint8_t *)peer_addr);
    EventCache.timeout = timeout;

    ESP_LOGW(TAG, "the ble data = %02x len = %ld g_cen_conn_handle = %d", ble_msg.buf[0], ble_msg.len,g_cen_conn_handle);

    if ((g_cen_conn_handle == 0xff) && (!ble_gap_conn_active()))       // 没连接 并且没在连接过程中
    {

        /* Scanning must be stopped before a connection can be initiated. */
        rc = ble_gap_disc_cancel();
        if (rc != 0)
        {
            ESP_LOGE("ble_gap_disc_cancel", "ble_gap_disc_cancel err");
            MODLOG_DFLT(ERROR, "Failed to cancel scan; rc=%d\n", rc);
            // return;
        }
        struct ble_gap_conn_params conn_params = {
            .scan_itvl = 0x0010,           // 10ms
            .scan_window = 0x0010,         // 10ms，等于 scan_itvl 表示持续扫描
            .itvl_min = 0x0018,            // 30ms 最小连接间隔
            .itvl_max = 0x0028,            // 50ms 最大连接间隔
            .latency = 0,                  // 不允许跳过连接事件（最及时）
            .supervision_timeout = 0x0100, // 2.56s 超时
            .min_ce_len = 0x0010,
            .max_ce_len = 0x0300,
        };

        addr.type = BLE_ADDR_PUBLIC;
        memcpy(addr.val, peer_addr, 6);

        // mac 地址 逆置
        for (int i = 0; i < 3; i++){
            uint8_t temp = addr.val[i];
            addr.val[i] = addr.val[5-i];
            addr.val[5-i] = temp;
        }

        ESP_LOGI(TAG,"now connecting %s ...",addr_str(addr.val));
        rc = ble_gap_connect(BLE_OWN_ADDR_PUBLIC, &addr, 30000, &conn_params, blecent_gap_event, &ble_msg);
        if (rc != 0)
        {
            MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d "
                               "addr=%s; rc=%d\n",
                        addr.type, addr_str(addr.val), rc);
            return;
        }
    }
    else // 连接后 或 连接中
    {
        ESP_LOGE(TAG,"It is already connected or in connecting process");
    }
}


void process_complete_data(uint8_t *data, uint16_t length) {
    // 处理完整的数据
    printf("Received complete data (%d bytes):\n", length);
    for (int i = 0; i < length; i++) {
        printf("%02X ", data[i]);
    }
    printf("\n");

    size_t out_len;
    // bleSendSuccessCnt++;
    MqttData_t *MqttSrc = EventCache.src;;

    if(MqttSrc) 
    {
        ESP_LOGI("process_complete_data", "length = %d", length);
        mbedtls_base64_encode((unsigned char *)&MqttSrc->lockCommandRequest.commandContent, sizeof(MqttSrc->lockCommandRequest.commandContent),\
                              &out_len, data,length);
        MqttSendCommandResponse(MqttSrc);
        
    }
    else
    {
        ESP_LOGW("process_complete_data", "MqttSrc == NULL");
    }
    
    if (EventCache.handler)
    {
        EventCache.handler(data, length);  
    }

    // 启动单次定时器,断开蓝牙连接

    ESP_LOGI(TAG, "EventCache.timeout = %d", EventCache.timeout);
    esp_err_t err = esp_timer_restart(one_shot_timer, EventCache.timeout * 1000);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "Failed to esp_timer_restart timer: %s", esp_err_to_name(err));
        return;
    }


    if(MqttSrc || EventCache.handler)
    {
        memset((uint8_t *)&EventCache, 0, sizeof(EventCache));
    }
    
    return;
}


static int blecent_gap_event(struct ble_gap_event *event, void *arg)
{
    struct ble_gap_conn_desc desc;
    int rc;
    struct ble_hs_adv_fields fields;
    app_bridged_device_t *device;
    uint8_t espnow_macaddr[6];

    switch (event->type)
    {

    case BLE_GAP_EVENT_DISC:
        espnow_macaddr[0] = event->disc.addr.val[5];
        espnow_macaddr[1] = event->disc.addr.val[4];
        espnow_macaddr[2] = event->disc.addr.val[3];
        espnow_macaddr[3] = event->disc.addr.val[2];
        espnow_macaddr[4] = event->disc.addr.val[1];
        espnow_macaddr[5] = event->disc.addr.val[0];
        device = app_bridge_get_device_by_espnow_macaddr(espnow_macaddr);
        /*
        if(device){
            ESP_LOGE(TAG, "Found Device (bda): %02x:%02x:%02x:%02x:%02x:%02x", event->disc.addr.val[5],\
                event->disc.addr.val[4],event->disc.addr.val[3],event->disc.addr.val[2],event->disc.addr.val[1],event->disc.addr.val[0]);
            esp_log_buffer_hex(TAG,event->disc.data,event->disc.length_data);
        }
        */

        rc = ble_hs_adv_parse_fields(&fields, event->disc.data,
                                     event->disc.length_data);
        if (rc != 0)
        {
            if (device)
                ESP_LOGE(TAG, "Failed to parse advertisement data; rc=%d\n", rc);
            return 0;
        } 
        if (fields.mfg_data_len > 16)
        {
            if (device)
            {
                device->dev_info.rssi = event->disc.rssi;
                if ((device->dev_info.is_online == false) || (get_timestamp_ms() - device->dev_info.last_update_time > 120000))
                {
                    device->dev_info.is_online = true;
                    DeviceLayer::PlatformMgr().ScheduleWork(UpdateLockReachableAttribute, reinterpret_cast<intptr_t>(device));
                    GetAppTask().AppScheduleWork(PublishOnlineStatus, reinterpret_cast<intptr_t>(device));
                }
                device->dev_info.last_update_time = get_timestamp_ms();
                if (fields.mfg_data[2] == 19)
                {
                    if (fields.mfg_data[21] == 1)
                    {
                        GetAppTask().AppScheduleWork(SendLockSyncTimeCommand, reinterpret_cast<intptr_t>(device));
                    }
                }

                if (memcmp(device->dev_info.ble_broadcast_data, fields.mfg_data, fields.mfg_data_len))
                {
                    // ESP_LOGE(TAG, "Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", event->disc.addr.val[5],
                    //          event->disc.addr.val[4], event->disc.addr.val[3], event->disc.addr.val[2], event->disc.addr.val[1], event->disc.addr.val[0]);
                    // ESP_LOGI(TAG, "manufacture_data_len = %d", fields.mfg_data_len);
                    esp_log_buffer_hex(TAG, fields.mfg_data, fields.mfg_data_len);
                    device->dev_info.change_bit = 0;
                    if (device->dev_info.device_status != fields.mfg_data[3])
                    {
                        if ((device->dev_info.device_status & 0x01) != (fields.mfg_data[3] & 0x01))
                            device->dev_info.change_bit |= DoorLockStatusBit;
                        device->dev_info.last_change_time = get_timestamp_ms();
                        if (fields.mfg_data[3] & 0x02)
                        {
                            // to do .. find the wired sensor firstly
                            app_bridged_device_t *sensor = app_bridge_get_sensor_by_sensor_id("FFFFFF");
                            if ((sensor) && ((device->dev_info.device_status & 0x04) != (fields.mfg_data[3] & 0x04)))
                            {
                                if (fields.mfg_data[3] & 0x04)
                                    sensor->dev_info.sensor_status = 1;
                                else
                                    sensor->dev_info.sensor_status = 2;
                                sensor->dev_info.last_change_time = get_timestamp_ms();
                                if (ENABLE_HOMEKIT_SENSOR)
                                    DeviceLayer::PlatformMgr().ScheduleWork(UpdateDoorSensorAttribute, reinterpret_cast<intptr_t>(sensor));
                                else
                                    ESP_LOGE(TAG, "Sensor status is %d, HOMEKIT sesnor function is disabled.", sensor->dev_info.sensor_status);

                                device->dev_info.change_bit |= DoorLockStatusBit;
                                if (sensor->dev_info.is_online == false)
                                {
                                    sensor->dev_info.is_online = true;
                                    DeviceLayer::PlatformMgr().ScheduleWork(UpdateLockReachableAttribute, reinterpret_cast<intptr_t>(sensor));
                                }
                            }
                        }

                        ESP_LOGE(TAG, "Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", event->disc.addr.val[5],
                                 event->disc.addr.val[4], event->disc.addr.val[3], event->disc.addr.val[2], event->disc.addr.val[1], event->disc.addr.val[0]);
                        ESP_LOGE(TAG, "Old Status:%02x, New Status:%02x", device->dev_info.device_status, fields.mfg_data[3]);

                        if (((device->dev_info.device_status & (SECURE_MODE_BIT | SECURE_MODE_BIT)) != (fields.mfg_data[3] & (SECURE_MODE_BIT | SECURE_MODE_BIT))) || ((device->dev_info.device_status & LOW_BAT_BIT) != (fields.mfg_data[3] & LOW_BAT_BIT)))
                        {
                            if (fields.mfg_data[3] & (SECURE_MODE_BIT | SECURE_MODE_BIT))
                                ESP_LOGE(TAG, "Secure Mode is on");
                            else
                                ESP_LOGE(TAG, "Secure Mode is off");

                            if (fields.mfg_data[3] & (LOW_BAT_BIT))
                            {
                                ESP_LOGE(TAG, "Low Battery");
                            }
                            else
                            {
                                ESP_LOGE(TAG, "Battery is normal");
                            }
                            device->dev_info.change_bit |= DoorLockStatusBit;
                        }

                        if ((device->dev_info.device_status & 0x01) != (fields.mfg_data[3] & 0x01))
                        {
                            device->dev_info.device_status = fields.mfg_data[3];
                            device->dev_info.reserve[0] = 0;
                            device->dev_info.reserve[0] = 0;
                            device->dev_info.reserve[0] = 0;
                            DeviceLayer::PlatformMgr().ScheduleWork(UpdateLockAttribute, reinterpret_cast<intptr_t>(device));
                        }
                        else
                            device->dev_info.device_status = fields.mfg_data[3];
                    }
                    if (memcmp(&device->dev_info.ble_broadcast_data[4], &fields.mfg_data[4], fields.mfg_data_len - 4))
                    {
                        device->dev_info.change_bit |= DoorlockEventBit;
                    }
                    memcpy(device->dev_info.ble_broadcast_data, fields.mfg_data, fields.mfg_data_len);
                    if (device->dev_info.change_bit)
                        GetAppTask().AppScheduleWork(PublishDoorLockStatus, reinterpret_cast<intptr_t>(device));
                }
                else
                {
                /*
                    ESP_LOGE(TAG, "Data No Change: Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", event->disc.addr.val[5],
                             event->disc.addr.val[4], event->disc.addr.val[3], event->disc.addr.val[2], event->disc.addr.val[1], event->disc.addr.val[0]);
                    esp_log_buffer_hex(TAG, fields.mfg_data, fields.mfg_data_len);
                */
                }
            }
        }
        else
        {
            // ESP_LOGE(TAG, "No manufacture data");
            app_bridged_device_t *device;
            uint8_t espnow_macaddr[6];
            espnow_macaddr[0] = event->disc.addr.val[5];
            espnow_macaddr[1] = event->disc.addr.val[4];
            espnow_macaddr[2] = event->disc.addr.val[3];
            espnow_macaddr[3] = event->disc.addr.val[2];
            espnow_macaddr[4] = event->disc.addr.val[1];
            espnow_macaddr[5] = event->disc.addr.val[0];
            device = app_bridge_get_device_by_espnow_macaddr(espnow_macaddr);
            if (device)
            {
                device->dev_info.rssi = event->disc.rssi;
                if ((device->dev_info.is_online == false) || (get_timestamp_ms() - device->dev_info.last_update_time > 120000))
                {
                    device->dev_info.is_online = true;
                    DeviceLayer::PlatformMgr().ScheduleWork(UpdateLockReachableAttribute, reinterpret_cast<intptr_t>(device));
                    GetAppTask().AppScheduleWork(PublishOnlineStatus, reinterpret_cast<intptr_t>(device));
                }
                device->dev_info.last_update_time = get_timestamp_ms();
            }
        }
        return 0;
        case BLE_GAP_EVENT_DISCONNECT:
        /* Connection terminated. */
        MODLOG_DFLT(INFO, "disconnect; reason=%d ", event->disconnect.reason);
        print_conn_desc(&event->disconnect.conn);
        MODLOG_DFLT(INFO, "\n");

        /* Forget about peer. */
        peer_delete(event->disconnect.conn.conn_handle);

        /* Resume scanning. */
        blecent_scan();
        connectedFlag = false;
        g_cen_conn_handle = 0xff;
        return 0;

    case BLE_GAP_EVENT_CONNECT:
        /* A new connection was established or a connection attempt failed. */
        if (event->connect.status == 0) {
            /* Connection successfully established. */
            g_cen_conn_handle = event->connect.conn_handle;
            MODLOG_DFLT(INFO, "Connection established g_cen_conn_handle = %d",g_cen_conn_handle);

            rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
            assert(rc == 0);
            print_conn_desc(&desc);
            MODLOG_DFLT(INFO, "\n");

            /* Remember peer. */
            rc = peer_add(event->connect.conn_handle);
            if (rc != 0) {
                MODLOG_DFLT(ERROR, "Failed to add peer; rc=%d\n", rc);
                return 0;
            }
            
            /* Perform service discovery */
            rc = peer_disc_all(event->connect.conn_handle,
                        blecent_on_disc_complete, arg);
            if(rc != 0) {
                MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc);
                return 0;
            }
        } else {
            /* Connection attempt failed; resume scanning. */
            MODLOG_DFLT(ERROR, "Error: Connection failed; status=%d\n",
                        event->connect.status);
            blecent_scan();
        }

        return 0;
    case BLE_GAP_EVENT_NOTIFY_RX:
        /* Peer sent us a notification or indication. */
        MODLOG_DFLT(INFO, "received %s; conn_handle=%d attr_handle=%d "
                          "attr_len=%d\n",
                    event->notify_rx.indication ? "indication" : "notification",
                    event->notify_rx.conn_handle,
                    event->notify_rx.attr_handle,
                    OS_MBUF_PKTLEN(event->notify_rx.om));

        /* Attribute data is contained in event->notify_rx.om. Use
         * `os_mbuf_copydata` to copy the data received in notification mbuf */
        // 接收到从机 的 数据
        esp_log_buffer_hex("yuezheng.gao received data form pher", event->notify_rx.om->om_data, event->notify_rx.om->om_len);

        // 连接确认,收到唤醒指令应答，表示连接正常
        if(!memcmp(event->notify_rx.om->om_data,weak_up_instruction_ack,8))
        {
            connectedFlag = true;
            ESP_LOGI("after connected", " g_cen_conn_handle = %d, ble_gap_conn_active = %d connectedFlag = %d", g_cen_conn_handle, ble_gap_conn_active(), connectedFlag);

            printf("Received weak_up_instruction_ack data (%d bytes):\n", event->notify_rx.om->om_len);
            for (int i = 0; i < event->notify_rx.om->om_len; i++)
            {
                printf("%02X ", event->notify_rx.om->om_data[i]);
            }
            printf("\r\n");

            esp_err_t err = esp_timer_start_once(one_shot_timer, 8000 * 1000);
            if (err != ESP_OK)
            {
                err = esp_timer_restart(one_shot_timer, 8000 * 1000);
                if (err != ESP_OK)
                {
                    ESP_LOGE(TAG, "Failed to esp_timer_restart timer: %s", esp_err_to_name(err));
                    return;
                }
            }
        }
        else // 非唤醒指令应答，业务逻辑处理
        {
            // 组包处理
            static uint16_t total_packet_len;
            static uint16_t offset = 0;
            static uint8_t total_ble_msg[256];

            if (!memcmp(event->notify_rx.om->om_data, BLE_HEAD, 4))
            {
                // 获取 ble 接收到的数据 总长度
                total_packet_len = ((uint16_t)event->notify_rx.om->om_data[5] << 8) | event->notify_rx.om->om_data[4];
            }

            if (total_packet_len > 0)
            {
                uint8_t one_pack_len = event->notify_rx.om->om_len;
                uint8_t *one_pack_data = event->notify_rx.om->om_data;
                memcpy(&total_ble_msg[offset], one_pack_data, one_pack_len);
                offset += one_pack_len;

                if (offset >= total_packet_len)
                {
                    process_complete_data(total_ble_msg, total_packet_len);
                    // 复位 数据缓存区 ，数据总长，数据偏移位置。
                    memset(total_ble_msg, 0x00, sizeof(total_ble_msg));
                    total_packet_len = 0;
                    offset = 0;
                }
            }
        }

    default:
        return 0;
    }
}
    

void BleDataForward(void * pvParameter)
{
    BleEvent evt;
    for (;;) {
        if ((connectedFlag == true) && (g_cen_conn_handle!=0xff) && (!ble_gap_conn_active()))
        {
            // 等待接收，阻塞直到队列中有数据 每组指令数据 至少间隔两秒发送
            if (xQueueReceive(bleEventQueue, &evt, (100 / portTICK_PERIOD_MS)) == pdTRUE)
            {
                send_ble_data_lock_when_connected(evt.buf,evt.len);
            }
        }
        vTaskDelay(100 / portTICK_PERIOD_MS);
        // ESP_LOGI("yuezheng,gao BleDataForward","g_cen_conn_handle = %d, ble_gap_conn_active = %d connectedFlag = %d", g_cen_conn_handle, ble_gap_conn_active(), connectedFlag);
    }
}